local skynet = require "skynet"
local json = require "cjson"
local websocket = require"websocket"
local dump_T = require "dump_t"

local pb = require "protobuf"
pb.register_file "./pbc/gctols.pb" 

local WATCHDOG
local CMD = {}
local client_fd
local user_info 
local handle={}
local gate
local room_idx
local room_pos
local uid

local function send_msg(fd,msg)
	websocket:send_binary(fd,msg)
end

--进入房间
local function enter_room(data)
	local room_id  
	if type(data) == "table" then
		room_id = data.roomid
	end
	local con_info ={
		fd = client_fd,
		watchdog = WATCHDOG,
		gate = gate,
		uid=uid,
		askid= data.askid or 0
	}
	local room_mgr_addr = skynet.uniqueservice"room_mgr"
	skynet.error("agent enter_room",room_mgr_addr,"room_id:",room_id)
	local ret,idx,pos = skynet.call(room_mgr_addr,"lua","enter",user_info,con_info,room_id)
	--skynet.error("----",json.encode(ret))
	room_idx = idx
	room_pos = pos
	if not ret then
		room_idx = nil
		room_pos = nil
		-- 返回加入失败
		local respJoinRoomData = {
			askid = data.askid,
			nflag = 1,
			nroomid = pos
		}
		local bytes = assert(pb.encode("GCToLS.RespJoinRoom", respJoinRoomData))
		local ReqXieYi = {
			msgid = "eMsg_JoinRoomAck",
			data = bytes,
		}
		local respData = assert(pb.encode("GCToLS.ReqXieYi", ReqXieYi))
		send_msg(client_fd,respData)
	end
end

local function exit_room(leavetype)
	if room_idx then
		local room_mgr_addr = skynet.uniqueservice"room_mgr"
		local ret = skynet.call(room_mgr_addr,"lua","exit",room_idx,room_pos,uid,leavetype)
		room_idx = nil
		room_pos = nil
	end
end

local function player_ready(data)
	if room_idx then
		print("player_ready room_idx = " .. room_idx)
		local room_mgr_addr = skynet.uniqueservice"room_mgr"
		data.uid = uid
		local ret = skynet.call(room_mgr_addr,"lua","prepare",room_idx,data)
	end
end

---------------------------socket数据处理----------------------------
local sock_handler = {}

-- 加入房间
sock_handler["eMsg_JoinRoom"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.ReqJoinRoom",rmsg.data))
	-- 根据是否有roomid,1有就是加入，没有就是随机进一个
	local data = {}
	if reqData.roomid then
		data.roomid = reqData.roomid
		data.askid = reqData.askid
	end
	enter_room(data)
end

-- 离开房间
sock_handler["eMsg_LeaveRoom"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.ReqLeaveRoom",rmsg.data))
	-- 根据是否有roomid,1有就是加入，没有就是随机进一个
	local data = {}
	if reqData.roomid then
		data.roomid = reqData.roomid
		data.askid = reqData.askid
	end
	exit_room()
end

-- 准备
sock_handler["eMsg_Ready"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.ReqReady",rmsg.data))
	-- 根据是否有roomid,1有就是加入，没有就是随机进一个
	local data = {}
	if reqData.roomid then
		data.roomid = reqData.roomid
		data.askid = reqData.askid
		data.nready = reqData.nready
	end
	player_ready(data)
end

-- 心跳
sock_handler["eMsg_Heart"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.ReqHeart",rmsg.data))
	local respHeartData = {
		askid = reqData.askid,
	}
	local bytes = assert(pb.encode("GCToLS.RespHeart", respHeartData))
	local ReqXieYi = {
		msgid = "eMsg_HeartAck",
		data = bytes,
	}
	local respData = assert(pb.encode("GCToLS.ReqXieYi", ReqXieYi))
	send_msg(fd, respData);
end

-- 玩家飞机移动
sock_handler["eMsg_ModifySelfPos"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.ReqModifySelfPos",rmsg.data))
	if room_idx then
		local position = reqData.pos
		local room_mgr_addr = skynet.uniqueservice"room_mgr"
		local ret = skynet.call(room_mgr_addr,"lua","player_plane_move",room_idx,room_pos,position)
	end
end

-- 玩家加载完成
sock_handler["eMsg_GameLoadFinish"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.RepGameLoadFinsh",rmsg.data))
	if room_idx then
		local room_mgr_addr = skynet.uniqueservice"room_mgr"
		local ret = skynet.call(room_mgr_addr,"lua","player_load_finish",room_idx,room_pos,reqData)
	end
end

-- 请求玩家位置
sock_handler["eMsg_PlayerTablsPos"] = function (fd, rmsg)
	local reqData = assert(pb.decode("GCToLS.ReqPlayerTablePos",rmsg.data))
	local room_mgr_addr = skynet.uniqueservice"room_mgr"
	local ret, roomid = skynet.call(room_mgr_addr,"lua","player_table_pos", uid)
	-- 返回加入失败
	local respPlayerTablePosData = {
		askid = reqData.askid,
		roomid = -1
	}
	if ret then
		respPlayerTablePosData.roomid = roomid
	end
	local bytes = assert(pb.encode("GCToLS.RespPlayerTablePos", respPlayerTablePosData))
	local ReqXieYi = {
		msgid = "eMsg_PlayerTablePosAck",
		data = bytes,
	}
	local respData = assert(pb.encode("GCToLS.ReqXieYi", ReqXieYi))
	send_msg(fd,respData)
end

skynet.register_protocol{
	name = "client",
	id = skynet.PTYPE_CLIENT,
	--解码
	unpack = function (data, sz)
		data = skynet.tostring(data,sz)
		if #data <= 2 then
			return
		end
		local msg = assert(pb.decode("GCToLS.ReqXieYi", data))
		return msg
	end,
	--处理
	dispatch = function(_,_,msg,...)
		if msg then
			if sock_handler[msg.msgid] then
				sock_handler[msg.msgid](client_fd, msg);
			end
		end
	end
}

function CMD.start(conf)
	local fd = conf.client
	gate = conf.gate
	WATCHDOG = conf.watchdog
	user_info = conf.info
	uid = conf.uid
	client_fd = fd
	skynet.call(gate,"lua","forward",fd)
end

function CMD.disconnect()
	exit_room(1)	
	skynet.error("agent exit!")
	skynet.exit()
end

skynet.start(function()
	skynet.dispatch("lua",function(_,_,cmd,...)
		local f = CMD[cmd]
		skynet.ret(skynet.pack(f(...)))
	end)
end)
